﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algobox.JuicyLib.Apps.NewedgeDownloader
{
    public static class FileDailyTrades
    {
        const char SEPERATOR_ROW = '\n';
        const char SEPERATOR_COL = ',';
        const int MIN_IX = 22;
        const int IX_PORTFOLIO = 0;
        const int IX_TRADEDATE = 3;
        const int IX_CCY = 4;
        const int IX_SEDOL = 6;
        const int IX_ISIN = 7;
        const int IX_RIC = 8;
        const int IX_NAME = 9;
        const int IX_SETTLEDATE = 10;
        const int IX_QUANTITY = 11;
        const int IX_PRICE = 12;
        const int IX_BROKERCODE = 23;
        const int IX_TRADEID = 26;


        public static bool ProcessData(string data, DateTime fileDate)
        {

            List<Algobox.JuicyLib.SQL.LiquidView.NewedgeDailyTrade> items = new List<Algobox.JuicyLib.SQL.LiquidView.NewedgeDailyTrade>();

            Algobox.JuicyLib.SQL.LiquidView.NewedgeDailyTrade item;
            Algobox.JuicyLib.SQL.LiquidView.InstrumentsStock stock;

            // remove strings in inverted commas from data completely
            string[] dataArray = data.Split('"');
            data = String.Empty;
            for (int i = 0; i < dataArray.Length; i++)
            {
                if (i % 2 == 0)
                    data += dataArray[i];
            }

            DateTime tradeDate, settlementDate;
            long quantity;
            decimal price, qtyTemp;
            int tradeId;

            var query = from csvline in data.Split(SEPERATOR_ROW)
                        let csv = csvline.Split(SEPERATOR_COL)
                        where csv.Length >= MIN_IX
                        select new
                        {
                            Portfolio = csv[IX_PORTFOLIO],
                            Sedol = csv[IX_SEDOL],
                            ISIN = csv[IX_ISIN],
                            RIC = csv[IX_RIC],
                            Name = csv[IX_NAME],
                            Quantity = csv[IX_QUANTITY],
                            Price = csv[IX_PRICE],
                            Currency = csv[IX_CCY],
                            TradeDate = csv[IX_TRADEDATE],
                            SettlementDate = csv[IX_SETTLEDATE],
                            BrokerCode = csv[IX_BROKERCODE],
                            TradeId = csv[IX_TRADEID]
                        };
            
            var enumerableQuery = query.GetEnumerator();
            for (int i = 0; enumerableQuery.MoveNext(); i++)
            {
                if (i == 0)
                    continue;

                var row = enumerableQuery.Current;

                try
                {
                    // tradeId
                    if (!Int32.TryParse(row.TradeId, out tradeId))
                    {
                        JuicyLib.SQL.LiquidView.LiquidViewHelper.LogException("NewedgeDownloader", "DailyTrades - Failed to parse tradeId for record RIC({0}) Account({1}) Quantity({2}) Price({3}) Date({4}) TradeId({5})", row.RIC, row.Portfolio, row.Quantity, row.Price, row.TradeDate, row.TradeId);
                        Console.WriteLine("DailyTrades Can't parse TradeId:  " + row.TradeId);
                        continue;
                    }
                    // quantity
                    if (!Decimal.TryParse(row.Quantity, out qtyTemp))
                    {
                        JuicyLib.SQL.LiquidView.LiquidViewHelper.LogException("NewedgeDownloader", "DailyTrades - Failed to parse quantity for record RIC({0}) Account({1}) Quantity({2}) Price({3}) TradeDate({4})", row.RIC, row.Portfolio, row.Quantity, row.Price, row.TradeDate);
                        Console.WriteLine("DailyTrades Can't parse quantity:  " + row.Quantity);
                        continue;
                    }
                    quantity = (int)qtyTemp;
                    // price
                    if (!Decimal.TryParse(row.Price, out price))
                    {
                        JuicyLib.SQL.LiquidView.LiquidViewHelper.LogException("NewedgeDownloader", "DailyTrades - Failed to parse price for record RIC({0}) Account({1}) Quantity({2}) Price({3}) TradeDate({4})", row.RIC, row.Portfolio, row.Quantity, row.Price, row.TradeDate);
                        Console.WriteLine("DailyTrades Can't parse price:  " + row.Price);
                        continue;
                    }
                    // trade date
                    if (!DateTime.TryParseExact(row.TradeDate,
                            "dd/MM/yyyy",
                            System.Globalization.CultureInfo.InvariantCulture,
                            System.Globalization.DateTimeStyles.None,
                            out tradeDate))
                    {
                        if (!DateTime.TryParseExact(row.TradeDate,
                           "dd-MM-yyyy",
                           System.Globalization.CultureInfo.InvariantCulture,
                           System.Globalization.DateTimeStyles.None,
                           out tradeDate))
                        {
                            JuicyLib.SQL.LiquidView.LiquidViewHelper.LogException("NewedgeDownloader", "DailyTrades - Failed to parse trade date for record RIC({0}) Account({1}) Quantity({2}) Price({3}) TradeDate({4})", row.RIC, row.Portfolio, row.Quantity, row.Price, row.TradeDate);
                            Console.WriteLine("DailyTrades Can't parse date:  " + row.TradeDate);
                            continue;
                        }
                    }
                    // settlement date
                    if (!DateTime.TryParseExact(row.SettlementDate,
                            "dd/MM/yyyy",
                            System.Globalization.CultureInfo.InvariantCulture,
                            System.Globalization.DateTimeStyles.None,
                            out settlementDate))
                    {
                        if (!DateTime.TryParseExact(row.SettlementDate,
                           "dd-MM-yyyy",
                           System.Globalization.CultureInfo.InvariantCulture,
                           System.Globalization.DateTimeStyles.None,
                           out settlementDate))
                        {
                            JuicyLib.SQL.LiquidView.LiquidViewHelper.LogException("NewedgeDownloader", "DailyTrades - Failed to parse settlement date for record RIC({0}) Account({1}) Quantity({2}) Price({3}) SettlementDate({4})", row.RIC, row.Portfolio, row.Quantity, row.Price, row.SettlementDate);
                            Console.WriteLine("DailyTrades Can't parse date:  " + row.TradeDate);
                            continue;
                        }
                    }
                    
                    if (row.Currency == "GBP")
                        price = price / 100;

                    item = new Algobox.JuicyLib.SQL.LiquidView.NewedgeDailyTrade();
                    item.Portfolio = row.Portfolio;
                    item.Quantity = quantity;
                    item.Price = price;
                    item.TradeDate = tradeDate;
                    item.SettlementDate = settlementDate;
                    item.BrokerCode = row.BrokerCode;
                    item.TradeId = tradeId;
                }
                catch
                {
                    continue;
                }


                if (!JuicyLib.SQL.LiquidView.LiquidViewHelper.TryGetInstrumentStock(row.RIC, out stock))
                {
                    string symbol;
                    if (row.RIC.Contains('.'))
                    {
                        symbol = row.RIC.Substring(0, row.RIC.IndexOf('.'));
                    }
                    else
                    {
                        symbol = row.RIC;
                    }

                    if (!JuicyLib.SQL.LiquidView.LiquidViewHelper.TryGetInstrumentStock(row.Currency, row.ISIN, row.Sedol, null, out stock))
                    {
                        if (!JuicyLib.SQL.LiquidView.LiquidViewHelper.TryGetInstrumentStock(row.Currency, row.ISIN, null, null, out stock))
                        {
                            if (!JuicyLib.SQL.LiquidView.LiquidViewHelper.TryGetInstrumentStock(row.Currency, null, row.Sedol, symbol, out stock))
                            {
                                if (!JuicyLib.SQL.LiquidView.LiquidViewHelper.TryGetInstrumentStock(row.Currency, null, null, symbol, out stock))
                                {
                                    if (!JuicyLib.SQL.LiquidView.LiquidViewHelper.TryCreateInstrumentStock(row.RIC, row.Currency, row.ISIN, row.Sedol, row.Name, null, out stock))
                                    {
                                        JuicyLib.SQL.LiquidView.LiquidViewHelper.LogException("NewedgeDownloader", "DailyTrades - Failed to find security for Currency({0}) ISIN({1}) Sedol({2}) RIC({3}) Symbol({4})", row.Currency, row.ISIN, row.Sedol, row.RIC, symbol);
                                        Console.WriteLine("Failed to find security for Currency({0}) ISIN({1}) Sedol({2}) RIC({3}) Symbol({4})", row.Currency, row.ISIN, row.Sedol, row.RIC, symbol);
                                        continue;
                                    }
                                    else
                                    {
#if !DEBUG
                                        JuicyLib.SQL.LiquidView.LiquidViewHelper.UpdateInstrumentStock(stock, null, null, row.RIC, null, null);
#endif
                                    }
                                }
                                else
                                {
#if !DEBUG
                                    JuicyLib.SQL.LiquidView.LiquidViewHelper.UpdateInstrumentStock(stock, row.ISIN, row.Sedol, row.RIC, null, null);
#endif
                                }
                            }
                            else
                            {
#if !DEBUG
                                JuicyLib.SQL.LiquidView.LiquidViewHelper.UpdateInstrumentStock(stock, row.ISIN, null, row.RIC, null, null);
#endif
                            }
                        }
                        else
                        {
#if !DEBUG
                            JuicyLib.SQL.LiquidView.LiquidViewHelper.UpdateInstrumentStock(stock, null, row.Sedol, row.RIC, null, null);
#endif
                        }
                    }
                    else
                    {
#if !DEBUG
                        JuicyLib.SQL.LiquidView.LiquidViewHelper.UpdateInstrumentStock(stock, null, null, row.RIC, null, null);
#endif
                    }
                }
                else
                {
#if !DEBUG
                    JuicyLib.SQL.LiquidView.LiquidViewHelper.UpdateInstrumentStock(stock, row.ISIN, row.Sedol, null, null, null);
#endif
                }

                Console.WriteLine("DailyTrades Added: {0} {1} {2} {3} {4} {5}", item.TradeDate, item.Portfolio, stock.Reuters, item.Quantity, item.Price, item.BrokerCode);

                item.StockId = stock.StockId;
                items.Add(item);
            }
            

            // remove previous data if exists
            foreach (string portfolio in items.Select(a => a.Portfolio).Distinct())
            {
                JuicyLib.SQL.LiquidView.LiquidViewHelper.TryRemoveNewedgeDailyTrades(fileDate, portfolio);
            }

            if (items.Count > 0)
            {
                if (JuicyLib.SQL.LiquidView.LiquidViewHelper.TryImportNewedgeDailyTrades(items))
                {
                    Console.WriteLine("DailyTrades Imported {0} open positions", items.Count);
                    return true;
                }
                else
                {
                    Console.WriteLine("DailyTrades Failed to import {0} AssetValuations", items.Count);
                }
            }

            return false;
        }


    }
}
